package com.sn.author.common.context;

import com.sn.author.common.config.AppConfig;
import com.sn.author.filter.content.UserDetail;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.io.Serializable;
import java.time.Instant;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtTokenHelper implements Serializable {

    private static final String CLAIM_KEY_USERNAME = "sub";

    /**
     * 签发JWT
     */
    public static String generateToken(UserDetail userDetails) {
        return generateToken(userDetails, AppConfig.jwtExpireTime);
    }

    /**
     * 签发JWT
     * @param userDetails 用户证书
     * @param expireTime  过期时间
     */
    public static String generateToken(UserDetail userDetails, Long expireTime){
        Map<String, Object> claims = new HashMap<>(16);
        claims.put( CLAIM_KEY_USERNAME, userDetails.getUser().getUserName() );

        return Jwts.builder()
                .setClaims( claims )
                .setExpiration( new Date( Instant.now().toEpochMilli() + expireTime  ) )
                .signWith( SignatureAlgorithm.HS512, AppConfig.jwtSecret )
                .compact();
    }

    /**
     * 验证JWT
     */
    public static Boolean validateToken(String token, UserDetail userDetails) {
        String username = getUsernameFromToken( token );

        return (username.equals( userDetails.getUser().getUserName() ) && !isTokenExpired( token ));
    }

    /**
     * 获取token是否过期
     */
    public static Boolean isTokenExpired(String token) {
        Date expiration = getExpirationDateFromToken( token );
        return expiration.before( new Date() );
    }

    /**
     * 根据token获取username
     */
    public static String getUsernameFromToken(String token) {
        return getClaimsFromToken( token ).getSubject();
    }

    /**
     * 获取token的过期时间
     */
    public static Date getExpirationDateFromToken(String token) {
        return getClaimsFromToken( token ).getExpiration();
    }

    /**
     * 解析JWT
     */
    private static Claims getClaimsFromToken(String token) {
            return Jwts.parser()
                    .setSigningKey(AppConfig.jwtSecret)
                    .parseClaimsJws( token )
                    .getBody();
    }
}
